package com.sh.rbac.core.mybatis.aspect;

import cn.hutool.core.util.StrUtil;
import com.sh.rbac.core.common.enums.DataScopeEnum;
import com.sh.rbac.core.mybatis.annotation.DataPermission;
import com.sh.rbac.core.mybatis.context.DataPermissionContext;
import com.sh.rbac.core.security.util.SecurityHolderUtils;
import com.sh.rbac.domain.entity.User;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * 数据权限切面
 *
 * @author wb
 * @since 2025-05-19
 */

@Slf4j
@Component
@Aspect
public class DataPermissionAspect {


    @Around("@annotation(dataPermission)")
    public Object doAround(ProceedingJoinPoint joinPoint, DataPermission dataPermission) throws Throwable {
        try {
            // 管理员，无需添加过滤条件
            if (SecurityHolderUtils.isAdmin()) {
                return joinPoint.proceed();
            }

            User user = SecurityHolderUtils.getLoginUser();
            Set<Integer> dataScopes = SecurityHolderUtils.getDataScopes();

            log.info("用户ID: {}, 数据权限: {}", user.getId(), dataScopes);

            if (dataScopes.isEmpty()) {
                return joinPoint.proceed();
            }

            Expression finalWhereCondition = null;

            // 从注解中获取字段别名
            String tableAlias = dataPermission.tableAlias().isEmpty() ? "" : dataPermission.tableAlias() + ".";
            String deptColumn = dataPermission.deptColumn();  // 部门字段名
            String userColumn = dataPermission.userColumn();  // 用户字段名
            boolean needJoinUser = dataPermission.needJoin(); // 是否关联用户表

            for (Integer dataScope : dataScopes) {
                Expression currentExpr = null;
                Long deptId = user.getDeptId();

                // 所有权限，无需添加过滤条件
                if (DataScopeEnum.DATA_SCOPE_ALL.getValue().equals(dataScope)) {
                    return joinPoint.proceed();
                }

                // 自定义数据权限
                if (DataScopeEnum.DATA_SCOPE_CUSTOM.getValue().equals(dataScope)) {
                    Set<Long> dataScopeDeptIds = SecurityHolderUtils.getDataScopeDeptIds();
                    if (!dataScopeDeptIds.isEmpty()) {
                        String deptIdsStr = StrUtil.join(",", dataScopeDeptIds);
                        if (needJoinUser) {
                            String subQuery = "(SELECT id FROM sys_user WHERE dept_id IN (" + deptIdsStr + "))";
                            currentExpr = CCJSqlParserUtil.parseCondExpression(
                                    tableAlias + userColumn + " IN " + subQuery
                            );
                        } else {
                            currentExpr = CCJSqlParserUtil.parseCondExpression(
                                    tableAlias + deptColumn + " IN (" + deptIdsStr + ")"
                            );
                        }
                    }
                }

                // 部门权限
                else if (DataScopeEnum.DATA_SCOPE_DEPT.getValue().equals(dataScope)) {
                    if (needJoinUser) {
                        String subQuery = "(SELECT id FROM sys_user WHERE dept_id = " + deptId + ")";
                        currentExpr = CCJSqlParserUtil.parseCondExpression(
                                tableAlias + userColumn + " IN " + subQuery
                        );
                    } else {
                        currentExpr = CCJSqlParserUtil.parseCondExpression(
                                tableAlias + deptColumn + " = " + deptId
                        );
                    }
                }

                // 部门及子部门权限
                else if (DataScopeEnum.DATA_SCOPE_DEPT_AND_CHILD.getValue().equals(dataScope)) {
                    String sql = String.format("select id from sys_dept where id = %d or parent_id = %d", deptId, deptId);
                    if (needJoinUser) {
                        String subQuery = "(SELECT id FROM sys_user WHERE dept_id IN (" + sql + "))";
                        currentExpr = CCJSqlParserUtil.parseCondExpression(
                                tableAlias + userColumn + " IN " + subQuery
                        );
                    } else {
                        currentExpr = CCJSqlParserUtil.parseCondExpression(
                                tableAlias + deptColumn + " IN (" + sql + ")"
                        );
                    }
                }

                // 本人权限
                else if (DataScopeEnum.DATA_SCOPE_SELF.getValue().equals(dataScope)) {
                    currentExpr = CCJSqlParserUtil.parseCondExpression(tableAlias + userColumn + " = " + user.getId()
                    );
                }

                if (currentExpr != null) {
                    if (finalWhereCondition == null) {
                        finalWhereCondition = currentExpr;
                    } else {
                        finalWhereCondition = new OrExpression(finalWhereCondition, currentExpr);
                    }
                }
            }

            log.info("数据权限过滤条件: {}", finalWhereCondition);
            DataPermissionContext.setCurrentExpression(finalWhereCondition);
            return joinPoint.proceed();
        } finally {
            DataPermissionContext.clear();
        }
    }


}
